﻿#include "ssClockWheel.h"


namespace StarSeeker
{

ssClockWheel::ssClockWheel()
{
	m_tick.tick = 0;
	m_timer.Init(SS_DIFF_TIMER_TYPE_SEC);
	m_ids.Init(1, 4000000000);
}

ssClockWheel::~ssClockWheel()
{
}

StarSeeker::u32 ssClockWheel::AddTimer(u32 msgType, u64 timestamp, u32 interval, ulint p1, ulint p2)
{
	u64 now = ssTime::GetTimeNow().u64p;
	if (now < timestamp)
	{
		u32 later = u32(timestamp - now);
		Tick_u tmp = m_tick;
		tmp._l1 += later % 256;
		tmp._l2 += later / 256;
		tmp._l3 += later / 256 * 256;
		tmp._l4 += later / 256 * 256 * 256;
		ssTimer_s msg;
		msg.msgID = msgType;
		msg.timestamp = tmp.tick;
		msg.interval = interval;
		msg.param[0] = p1;
		msg.param[1] = p2;
		msg.subID = m_ids.GetID();
		m_solt[tmp._l1].Push(msg);
		return msg.subID;
	}
	return 0;
}

u32 ssClockWheel::AddTimer(u32 msgType, u32 interval, ulint param1, ulint param2)
{
	Tick_u tmp = m_tick;
	tmp._l1 += interval % 256;
	tmp._l2 += interval / 256;
	tmp._l3 += interval / 256 * 256;
	tmp._l4 += interval / 256 * 256 * 256;
	ssTimer_s msg;
	msg.msgID = msgType;
	msg.timestamp = tmp.tick;
	msg.interval = interval;
	msg.param[0] = param1;
	msg.param[1] = param2;
	msg.subID = m_ids.GetID();
	m_solt[tmp._l1].Push(msg);
	return msg.subID;
}

void ssClockWheel::RemoveTimer(u32 timerId)
{
	for (u32 i = 0; i < SS_CLOCK_SOLT; i++)
	{
		if (m_solt[i].Delete(timerId))
		{
			break;
		}
	}
}

void ssClockWheel::StartHalfTimer()
{
	u64 now = ssTime::GetTimeNow().u64p;
	u64 beg = 1800 - now % 1800;
	AddTimer(SS_TIMER_HALF_HOUR, (u32)beg, 0, 0);
}

void ssClockWheel::AddTick()
{
	++m_tick.tick;
	std::list<ssTimer_s>* plist = m_solt[m_tick._l1].GetList(m_tick.tick);
	if (plist && !plist->empty())
	{
		for (std::list<ssTimer_s>::iterator itr2 = plist->begin(); itr2 != plist->end(); ++itr2)
		{
			switch (itr2->msgID)
			{
			case SS_TIMER_ONCE:
				//Dispatch(itr2->msgID, itr2->subID, itr2->param[0], itr2->param[1]);
				OnTimerOnce(itr2->subID, itr2->param[0], itr2->param[1]);
				break;
			case SS_TIMER_REPEAT:
				//Dispatch(itr2->msgID, itr2->subID, itr2->param[0], itr2->param[1]);
				OnTimerRepeat(itr2->subID, itr2->param[0], itr2->param[1]);
				m_temp.push_back(*itr2);
				break;
			case SS_TIMER_HALF_HOUR:
				//Dispatch(itr2->msgID, itr2->subID, itr2->param[0], itr2->param[1]);
				OnTimerHalfHour(itr2->subID, itr2->param[0], itr2->param[1]);
				itr2->interval = 1800;
				m_temp.push_back(*itr2);
				break;
			default:
				break;
			}
		}
		plist->clear();
		if (!m_temp.empty())
		{
			for (std::list<ssTimer_s>::iterator itr = m_temp.begin(); itr != m_temp.end(); ++itr)
			{
				Readd(*itr, itr->interval);
			}
			m_temp.clear();
		}
	}
}

void ssClockWheel::Readd(ssTimer_s& msg, u32 interval)
{
	Tick_u tmp = m_tick;
	tmp._l1 += interval % 256;
	tmp._l2 += interval / 256;
	tmp._l3 += interval / 256 * 256;
	tmp._l4 += interval / 256 * 256 * 256;
	msg.timestamp = tmp.tick;
	msg.interval = interval;
	m_solt[tmp._l1].Push(msg);
}

void ssClockWheel::Update()
{
	m_timer.UpdateTime();
	if (m_timer.GetDifference().i64p > 0)
	{
		for (i64 i = 0; i < m_timer.GetDifference().i64p; ++i)
		{
			AddTick();
		}
	}
}

}
